<script lang="ts" setup>
import { ref, onMounted, computed, watch } from 'vue';
import { GetPortsList, OpenPort, ClosePort, SendData, GetMessages, ClearMessages, IsPortOpen, GetCurrentConfig, CalculateModbusCRC, AppendModbusCRC, VerifyModbusCRC } from '../wailsjs/go/main/App';
import { EventsOn } from '../wailsjs/runtime/runtime';

// 串口配置
const portsList = ref<string[]>([]);
const selectedPort = ref('');
const baudRates = [1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200];
const selectedBaudRate = ref(9600);
const dataBits = [5, 6, 7, 8];
const selectedDataBits = ref(8);
const parityOptions = [
  { value: 'N', label: '无校验(N)' },
  { value: 'E', label: '偶校验(E)' },
  { value: 'O', label: '奇校验(O)' },
  { value: 'M', label: '标记(M)' },
  { value: 'S', label: '空格(S)' }
];
const selectedParity = ref('N');
const stopBitsOptions = [
  { value: 1, label: '1位' },
  { value: 1.5, label: '1.5位' },
  { value: 2, label: '2位' }
];
const selectedStopBits = ref(1);
const isPortOpen = ref(false);
const portStatus = computed(() => isPortOpen.value ? '已打开' : '已关闭');
const portStatusClass = computed(() => isPortOpen.value ? 'text-success' : 'text-danger');

// 发送区域
const sendData = ref('');
const sendFormat = ref('hex');
const autoAppendCRC = ref(false);

// 接收区域
const messages = ref<any[]>([]);
const autoScroll = ref(true);
const displayFormat = ref('hex');

// 加载串口列表
const loadPortsList = async () => {
  try {
    portsList.value = await GetPortsList();
    if (portsList.value.length > 0) {
      selectedPort.value = portsList.value[0];
    }
  } catch (error) {
    console.error('获取串口列表失败:', error);
  }
};

// 打开/关闭串口
const togglePort = async () => {
  try {
    if (isPortOpen.value) {
      await ClosePort();
      isPortOpen.value = false;
    } else {
      await OpenPort({
        portName: selectedPort.value.split(' ')[0], // 提取端口名称（去除可能的描述部分）
        baudRate: selectedBaudRate.value,
        dataBits: selectedDataBits.value,
        parity: selectedParity.value,
        stopBits: selectedStopBits.value,
        flowControl: 'none'
      });
      isPortOpen.value = true;

      // 加载当前消息
      const currentMessages = await GetMessages();
      messages.value = currentMessages;
    }
  } catch (error) {
    console.error('操作串口失败:', error);
    alert(`操作串口失败: ${error}`);
  }
};

// 发送数据
const handleSendData = async () => {
  if (!isPortOpen.value) {
    alert('请先打开串口');
    return;
  }

  try {
    let dataToSend = sendData.value;

    // 如果是十六进制格式，验证输入
    if (sendFormat.value === 'hex') {
      // 移除所有空格
      dataToSend = dataToSend.replace(/\s+/g, '');

      // 验证是否为有效的十六进制
      if (!/^[0-9A-Fa-f]*$/.test(dataToSend)) {
        alert('请输入有效的十六进制数据');
        return;
      }

      // 如果字符数为奇数，添加前导零
      if (dataToSend.length % 2 !== 0) {
        dataToSend = '0' + dataToSend;
      }

      // 如果需要添加CRC
      if (autoAppendCRC.value) {
        try {
          dataToSend = await AppendModbusCRC(dataToSend);
        } catch (error) {
          alert(`CRC计算失败: ${error}`);
          return;
        }
      }
    }

    await SendData(dataToSend, sendFormat.value);
  } catch (error) {
    console.error('发送数据失败:', error);
    alert(`发送数据失败: ${error}`);
  }
};

// 清除消息
const clearMessages = async () => {
  await ClearMessages();
  messages.value = [];
};

// 计算CRC
const calculateCRC = async () => {
  if (sendFormat.value !== 'hex') {
    alert('CRC计算仅支持十六进制格式');
    return;
  }

  try {
    // 移除所有空格
    const data = sendData.value.replace(/\s+/g, '');

    // 验证是否为有效的十六进制
    if (!/^[0-9A-Fa-f]*$/.test(data)) {
      alert('请输入有效的十六进制数据');
      return;
    }

    const crc = await CalculateModbusCRC(data);
    alert(`CRC校验值: ${crc}`);
  } catch (error) {
    console.error('CRC计算失败:', error);
    alert(`CRC计算失败: ${error}`);
  }
};

// 验证CRC
const verifyCRC = async () => {
  if (sendFormat.value !== 'hex') {
    alert('CRC验证仅支持十六进制格式');
    return;
  }

  try {
    // 移除所有空格
    const data = sendData.value.replace(/\s+/g, '');

    // 验证是否为有效的十六进制
    if (!/^[0-9A-Fa-f]*$/.test(data)) {
      alert('请输入有效的十六进制数据');
      return;
    }

    const isValid = await VerifyModbusCRC(data);
    alert(isValid ? 'CRC校验通过' : 'CRC校验失败');
  } catch (error) {
    console.error('CRC验证失败:', error);
    alert(`CRC验证失败: ${error}`);
  }
};

// 格式化十六进制显示
const formatHex = (hex: string): string => {
  // 每两个字符添加一个空格
  return hex.match(/.{1,2}/g)?.join(' ') || '';
};

// 十六进制转ASCII
const hexToAscii = (hex: string): string => {
  let ascii = '';
  for (let i = 0; i < hex.length; i += 2) {
    const charCode = parseInt(hex.substr(i, 2), 16);
    // 只显示可打印字符，其他用.代替
    ascii += (charCode >= 32 && charCode <= 126) ? String.fromCharCode(charCode) : '.';
  }
  return ascii;
};

// 监听新消息事件
onMounted(() => {
  loadPortsList();

  // 检查端口是否已打开
  IsPortOpen().then(status => {
    isPortOpen.value = status;
  });

  // 监听新消息
  EventsOn('serial-message', (message) => {
    messages.value.push(message);

    // 自动滚动到底部
    if (autoScroll.value) {
      setTimeout(() => {
        const messagesContainer = document.getElementById('messages-container');
        if (messagesContainer) {
          messagesContainer.scrollTop = messagesContainer.scrollHeight;
        }
      }, 0);
    }
  });
});
</script>

<template>
  <div class="container mx-auto p-4 max-w-6xl bg-gray-50">
    <h1 class="text-2xl font-bold mb-4 text-center text-primary">串口调试助手</h1>

    <!-- 主布局：左侧配置，右侧接收/发送 -->
    <div class="flex flex-col md:flex-row gap-4">
      <!-- 左侧：串口配置区域 -->
      <div class="md:w-1/4 bg-gray-200 p-4 rounded-lg shadow-sm">
        <h2 class="text-lg font-bold mb-3 text-gray-800">串口配置</h2>
        <div class="mb-4">
          <label class="block text-sm font-bold mb-1 text-gray-800">串口</label>
          <div class="flex gap-2">
            <select v-model="selectedPort"
              class="flex-1 border border-gray-400 rounded p-2 text-sm bg-white text-gray-800 shadow-sm">
              <option v-for="port in portsList" :key="port" :value="port">{{ port }}</option>
            </select>
            <button @click="loadPortsList"
              class="bg-info text-white px-3 py-2 rounded text-sm font-medium shadow-sm hover:opacity-90">刷新</button>
          </div>
        </div>

        <div class="mb-4">
          <label class="block text-sm font-bold mb-1 text-gray-800">波特率</label>
          <select v-model="selectedBaudRate"
            class="w-full border border-gray-400 rounded p-2 text-sm bg-white text-gray-800 shadow-sm">
            <option v-for="rate in baudRates" :key="rate" :value="rate">{{ rate }}</option>
          </select>
        </div>

        <div class="mb-4">
          <label class="block text-sm font-bold mb-1 text-gray-800">数据位</label>
          <select v-model="selectedDataBits"
            class="w-full border border-gray-400 rounded p-2 text-sm bg-white text-gray-800 shadow-sm">
            <option v-for="bits in dataBits" :key="bits" :value="bits">{{ bits }}</option>
          </select>
        </div>

        <div class="mb-4">
          <label class="block text-sm font-bold mb-1 text-gray-800">校验位</label>
          <select v-model="selectedParity"
            class="w-full border border-gray-400 rounded p-2 text-sm bg-white text-gray-800 shadow-sm">
            <option v-for="option in parityOptions" :key="option.value" :value="option.value">{{ option.label }}
            </option>
          </select>
        </div>

        <div class="mb-4">
          <label class="block text-sm font-bold mb-1 text-gray-800">停止位</label>
          <select v-model="selectedStopBits"
            class="w-full border border-gray-400 rounded p-2 text-sm bg-white text-gray-800 shadow-sm">
            <option v-for="option in stopBitsOptions" :key="option.value" :value="option.value">{{ option.label }}
            </option>
          </select>
        </div>

        <button @click="togglePort" :class="isPortOpen ? 'bg-danger' : 'bg-success'"
          class="text-white px-4 py-2 rounded w-full font-medium shadow-sm hover:opacity-90 mb-2">
          {{ isPortOpen ? '关闭串口' : '打开串口' }}
        </button>

        <div class="text-sm text-black-400">
          状态: <span :class="[portStatusClass, 'font-bold']">{{ portStatus }}</span>
        </div>
      </div>
      
      <!-- 右侧：接收和发送区域 -->
      <div class="md:w-3/4 flex flex-col gap-4">
        <!-- 接收区域 -->
        <div class="bg-gray-200 p-4 rounded-lg shadow-sm flex-1">
          <div class="flex justify-between items-center mb-2">
            <h2 class="text-lg font-bold text-gray-800">接收区域</h2>
            <div class="flex gap-2">
              <label class="flex items-center bg-white px-2 py-1 rounded border border-gray-400">
                <input type="checkbox" v-model="autoScroll" class="mr-1">
                <span class="text-sm font-medium text-gray-800">自动滚动</span>
              </label>
              <select v-model="displayFormat" class="border border-gray-400 rounded p-1 text-sm bg-white text-gray-800">
                <option value="hex">HEX</option>
                <option value="ascii">ASCII</option>
              </select>
              <button @click="clearMessages"
                class="bg-danger text-white px-3 py-1 rounded text-sm font-medium shadow-sm hover:opacity-90">清除</button>
            </div>
          </div>

          <div id="messages-container"
            class="bg-white border border-gray-400 rounded p-2 h-64 overflow-y-auto font-mono text-sm shadow-inner text-left">
            <div v-for="(msg, index) in messages" :key="index" class="mb-1 text-left">
              <span class="text-gray-700 font-medium">{{ msg.timestamp }}</span>
              <span :class="msg.direction === 'send' ? 'text-primary font-bold' : 'text-success font-bold'" class="ml-2">
                {{ msg.direction === 'send' ? '发送' : '接收' }}:
              </span>
              <span class="ml-2 text-gray-900">
                {{ displayFormat === 'hex' ? formatHex(msg.data) : hexToAscii(msg.data) }}
              </span>
            </div>
          </div>
        </div>

        <!-- 发送区域 -->
        <div class="bg-gray-200 p-4 rounded-lg shadow-sm flex-1">
          <div class="flex justify-between items-center mb-2">
            <h2 class="text-lg font-bold text-gray-800">发送区域</h2>
            <div class="flex gap-2">
              <select v-model="sendFormat" class="border border-gray-400 rounded p-1 text-sm bg-white text-gray-800">
                <option value="hex">HEX</option>
                <option value="ascii">ASCII</option>
              </select>
              <label class="flex items-center bg-white px-2 py-1 rounded border border-gray-400">
                <input type="checkbox" v-model="autoAppendCRC" class="mr-1">
                <span class="text-sm font-medium text-gray-800">自动添加CRC</span>
              </label>
            </div>
          </div>

          <textarea v-model="sendData"
            class="w-full border border-gray-400 rounded p-2 h-32 font-mono text-sm mb-2 bg-white text-gray-800 shadow-inner"
            placeholder="输入要发送的数据..."></textarea>

          <div class="flex gap-2">
            <button @click="handleSendData"
              class="bg-primary text-white px-4 py-2 rounded flex-1 font-medium shadow-sm hover:opacity-90">发送</button>
            <button @click="calculateCRC"
              class="bg-secondary text-white px-4 py-2 rounded font-medium shadow-sm hover:opacity-90">计算CRC</button>
            <button @click="verifyCRC"
              class="bg-info text-white px-4 py-2 rounded font-medium shadow-sm hover:opacity-90">验证CRC</button>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>